iT邦幫忙

2022 iThome 鐵人賽

DAY 13
1
Modern Web

你 React 了嗎? 30 天解鎖 React 技能系列 第 13

[DAY 13] React 引入圖片檔案,圖片懶加載與預加載

  • 分享至 

  • xImage
  •  

[情境任務]

小當家:客人點了一大桌的桌菜,真是累死我了!

解師傅:哇~這些菜看起來太美味了!看看那個醬汁!讓我拍個照先~

解師傅拍的照片真漂亮,我們把它們放在菜單上吧!


cover

設置外部圖片

<img src="https://picsum.photos/200/300?random=1" alt=""/>

要放圖片其實很簡單,如果是外部的圖片,可以直接像平常 HTML 的方式 src="圖片網址" 設置


引入內部圖片檔案

如果是引入在專案中的圖片,有兩種方式

  • 使用 require 將圖檔引入
  • 使用 import 將圖檔引入

1. 使用 require 將圖檔引入

<img src={require('./images/logo.jpg')} alt=""/>

require 方法是 CommonJs 推出的,NodeJs 自帶了這個功能


2.使用 import 將圖檔引入

import Img from "./images/react.jpg";

function App() {
  return (
    <img src={Img} alt=""/>
  );
}

export default App;

import 是 ES6 的語法,透過 Babel 轉譯後還是會使用 CommonJS 加載,也就是如果你寫了 import 最後還是會被轉成 require,import 的寫法等同於第一種的 require 方法


兩種方法效能上基本上沒區別,因為轉譯過後還是一樣的東西


不過以 require / exports 來說,只有簡單的寫法

const demo = require('demo')
exports.demo = demo 
module.exports = demo 

而 import / export 的寫法就很多樣了

import demo from 'demo'
import { default as demo } from 'demo'
import * as demo from 'demo'
import { readFile } from 'demo'
import { readFile as read } from 'demo'
import demo, { readFile } from 'demo'

export default demo 
export const demo 
export function readFile
export { readFile, read }
export * from 'demo'

import 屬於靜態編譯,所以沒辦法動態加載,但 require 可以

const url = "a" + "b"

import url // X 錯誤
require(url) // OK

圖片懶加載(Lazy load)

講完如何載入圖片,來談談圖片的懶加載。

有些網站載入時,一開始圖片會有一個佔位符,可能是一個色塊或是一個佔位符圖片,當滾輪往下移動時,真正的圖片才顯示出來,像 unsplash 就是一個例子

unsplash

圖片懶加載可以節省一堆圖片的運算,滾到需要顯示的圖片才載入,頁面的加載速度會比較快,不占用後台資源,頁面的速度也利於 SEO,適用在圖片較多的地方,如電商、圖片素材庫等

缺點

  • 因要監聽圖片是否顯示,較耗瀏覽器效能
  • 如網路不好,圖片會很慢才顯示,會有一段空白時間

推薦一個簡易就可以達到圖片懶加載的套件 React Lazy Load Image Component


React Lazy Load Image 使用方法

  • 安裝 React Lazy Load Image Component
  • 載入 LazyLoadImage 組件
  • 使用 LazyLoadImage 組件
  • 添加佔位符圖片
  • 添加佔位符模糊效果

1. 安裝 React Lazy Load Image Component

// Yarn
$ yarn add react-lazy-load-image-component

// NPM
$ npm i --save react-lazy-load-image-component

你可以用 npm 或 yarn 來安裝 react-lazy-load-image-component


2. 載入 LazyLoadImage 組件

import Image from "../images/dog.jpg";
import { LazyLoadImage } from "react-lazy-load-image-component";

載入 LazyLoadImage 就可以使用此組件


3. 使用 LazyLoadImage 組件

import Image from "../images/dog.jpg";
import { LazyLoadImage } from "react-lazy-load-image-component";

export default function App() {
  return (
    <div>
      <LazyLoadImage 
		src={Image}
        width={500} 
		height={500}
        alt=""
      />
     </div>
  );
}

img 的標籤改為 LazyLoadImage 組件,並明確加上寬高,以避免累積佈局偏移(CLS)問題,到這邊已經可以有 lazy load 的效果,附上 codesandbox 程式碼範例 可以觀察看看


4. 添加佔位符圖片

import Image from "../images/dog.jpg";
import PlaceholderImage from "../images/placeholder.jpg";
import { LazyLoadImage } from 'react-lazy-load-image-component';

<LazyLoadImage 
    src={Image}
    width={600} 
    height={400}
    placeholdersrc={PlaceholderImage}
    alt=""
/>

可以準備一張低解析的佔位符圖片,是用來滾下卷軸前顯示的圖片,並指向 placeholdersrc 屬性


5. 添加佔位符模糊效果

import Image from "../images/dog.jpg";
import PlaceholderImage from "../images/placeholder.jpg";
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';

<LazyLoadImage 
	src={Image}
    width={600} 
	height={400}
    placeholdersrc={PlaceholderImage}
	effect="blur"
    alt=""
/>

佔位符圖片也可以有模糊效果,顯示圖片前會將圖片模糊,需載入 css,並加入屬性 effect="blur"

可以打開 Network 看看 Img 的變化,在滾動之前 Img 會是空的,直到滾到圖片的地方才載入,將 Network 調到 Slow 3G 效果會更明顯

network

這邊附上 Demo,一起觀察看看吧!


圖片預加載

有懶加載就會有預加載,預加載跟懶加載相反,頁面一進來就先把圖片都先載入,將圖片存入緩存,圖片就不會有延遲的效果,可以享受無需等待直接預覽的效果,適用的地方如漫畫、圖片畫廊等不希望讓用戶看到加載時空白的場景

缺點

  • 預加載會占用較多後台資源
  • 頁面一開始載入的時間較長
import image1 from "../images/image1.jpg";
import image2 from "../images/image2.jpg";
import image3 from "../images/image3.jpg";

useEffect(() => {
  const imageList = [image1, image2, image3]
  imageList.forEach((image) => {
    new Image().src = image
  });
}, [])

[任務解題]

圖片的部分,這邊用了 Lorem Picsum 的 random 圖片作替代,也加上了 lazy-load 的效果

menu

菜單的圖片也完成囉!打開 codesandbox 程式碼範例 看看吧!


結語

圖片載入的方法可以用 require 或 import,個人是比較喜歡用 ES6 import 的寫法,我們也學到了懶加載和預加載使用方法,可以依據需求或適用情境去做加載,一起練習看看吧!/images/emoticon/emoticon12.gif


Reference

JavaScript 中 require, import 的差別及效能
如何在React 中實現圖片懶加載
超詳細的圖片預加載和懶加載教程


本文將同步更新至我的部落格
Lala 的前端大補帖



上一篇
[DAY 12] 條件式 render 與 && 邏輯運算子
下一篇
[DAY 14] 塞入你的 HTML-dangerouslySetInnerHTML
系列文
你 React 了嗎? 30 天解鎖 React 技能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
APPX Jim
iT邦新手 5 級 ‧ 2022-09-28 14:12:37

感覺很實用 ~ 先收藏起來 ~ 謝

Lala Code iT邦新手 4 級 ‧ 2022-09-29 17:44:53 檢舉

不客氣~~/images/emoticon/emoticon12.gif

我要留言

立即登入留言